#include "stdafx.h"
#include "CppUnitTest.h"
#include <HSModel/RayDirectionPicking.h>
#include <HSModel/SharedConstants.h>
using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace HSModelTests
{
	TEST_CLASS(RayDirectionPickingTest)
	{
	public:
		
		TEST_METHOD(ShouldTriangulateCellsAsInGround)
		  {
			Cell cell(0,0);
      Heights heights(0, 3, 3, 0);
      auto triangles = GetTrianglesByCell(cell, heights);
      auto up=triangles.first;
      TVector3 u_l_point =up.V[1];
      TVector3 u_r_point =up.V[2];
		  TVector3 b_l_point =up.V[0];
      Assert::AreEqual(0.0, u_l_point[0]);
      Assert::AreEqual(0.0, u_l_point[1]);
      Assert::AreEqual(0.0, u_l_point[2]);
      Assert::AreEqual(0.0, u_r_point[0]);
      Assert::AreEqual(10.0, u_r_point[1]);
      Assert::AreEqual(30.0, u_r_point[2]);
      Assert::AreEqual(10.0, b_l_point[0]);
      Assert::AreEqual(0.0, b_l_point[1]);
      Assert::AreEqual(30.0, b_l_point[2]);
    
      auto down = triangles.second;
      u_r_point = down.V[2];
		  b_l_point = down.V[1];
      TVector3 b_r_point = down.V[0];
      
      Assert::AreEqual(10.0, b_r_point[0]);
      Assert::AreEqual(10.0, b_r_point[1]);
      Assert::AreEqual(0.0, b_r_point[2]);
      Assert::AreEqual(0.0, u_r_point[0]);
      Assert::AreEqual(10.0, u_r_point[1]);
      Assert::AreEqual(30.0, u_r_point[2]);
      Assert::AreEqual(10.0, b_l_point[0]);
      Assert::AreEqual(0.0, b_l_point[1]);
      Assert::AreEqual(30.0, b_l_point[2]);

      }

    TEST_METHOD(ShouldPickTrianglesByHeightMap1)
		  {
			HeightMap map (3, 3);
      map.Set(0, 0, 0);
      map.Set(1, 0, 10);
      map.Set(2, 0, 0);
      map.Set(0, 1, 9);
      map.Set(1, 1, 0);
      map.Set(2, 1, 10);
      map.Set(0, 2, 0);
      map.Set(1, 2, 9);
      map.Set(2, 2, 0);
      TLine3 line ( TVector3(0, 0, 5), TVector3(1, 1, 0) );
      auto triangles=PickTrianglesWithCellsAndLine(map, line);
      Assert::AreEqual(size_t(4), triangles.size());
      }

    TEST_METHOD(ShouldPickTrianglesByHeightMap2)
		  {
			HeightMap map (31, 31);
      map.Set(15, 15, 10);
      TLine3 line ( TVector3(0, 0, 5), TVector3(1, 1, 0) );
      auto triangles=PickTrianglesWithCellsAndLine(map, line);
      Assert::AreEqual(size_t(2), triangles.size());
      auto triangle  = triangles[0];
      TVector3 b_r_point =triangle.V[0];
      TVector3 b_l_point =triangle.V[1];
		  TVector3 u_r_point =triangle.V[2];
      
      Assert::AreEqual(150.0, b_r_point[0]);
      Assert::AreEqual(150.0, b_r_point[1]);
      Assert::AreEqual(100.0, b_r_point[2]);
      Assert::AreEqual(140.0, u_r_point[0]);
      Assert::AreEqual(150.0, u_r_point[1]);
      Assert::AreEqual(0.0, u_r_point[2]);
      Assert::AreEqual(150.0, b_l_point[0]);
      Assert::AreEqual(140.0, b_l_point[1]);
      Assert::AreEqual(0.0, b_l_point[2]);
      }

    TEST_METHOD(ShouldPickTrianglesByHeightMap3)
		  {
			HeightMap map (31, 31);
      map.Set(15, 15, 10);
      TLine3 line(TVector3(146, 146, 50), TVector3(0, 0, -1));
      auto triangles=PickTrianglesWithCellsAndLine(map, line);
      Assert::AreEqual(size_t(1), triangles.size());
      auto triangle  = triangles[0];
      TVector3 b_r_point =triangle.V[0];
      TVector3 b_l_point =triangle.V[1];
		  TVector3 u_r_point =triangle.V[2];
      
      Assert::AreEqual(150.0, b_r_point[0]);
      Assert::AreEqual(150.0, b_r_point[1]);
      Assert::AreEqual(100.0, b_r_point[2]);
      Assert::AreEqual(140.0, u_r_point[0]);
      Assert::AreEqual(150.0, u_r_point[1]);
      Assert::AreEqual(0.0, u_r_point[2]);
      Assert::AreEqual(150.0, b_l_point[0]);
      Assert::AreEqual(140.0, b_l_point[1]);
      Assert::AreEqual(0.0, b_l_point[2]);
      
      TLine3 line1 ( TVector3(146, 50, 146), TVector3(0.0004, 1, 0.0004) );
      triangles=PickTrianglesWithCellsAndLine(map, line1);
      Assert::AreEqual(size_t(0), triangles.size());
      }
    
    TEST_METHOD(ShouldPickCellsWnenXdirPositive)
		  {
			HeightMap map (5, 5);
      TRay2 ray ( TVector2(-10, 0), TVector2(1, 1) );
      auto cell_list = PickNeededCells(map, ray);
      Assert::AreEqual( cell_list.size(), size_t(5));
      Assert::AreEqual( cell_list[0].first, size_t(0));
      Assert::AreEqual( cell_list[0].second, size_t(1));
      Assert::AreEqual( cell_list[4].first, size_t(2));
      Assert::AreEqual( cell_list[4].second, size_t(3));
      
      TRay2 ray1 ( TVector2(-10, 10), TVector2(3.5, 1.0) );
      cell_list = PickNeededCells(map, ray1);
      Assert::AreEqual( cell_list.size(), size_t(5));
      Assert::AreEqual( cell_list[2].first, size_t(2));
      Assert::AreEqual( cell_list[2].second, size_t(1));
      Assert::AreEqual( cell_list[4].first, size_t(3));
      Assert::AreEqual( cell_list[4].second, size_t(2));

      TRay2 ray2 ( TVector2(20, 70), TVector2(1, -4) );
      cell_list = PickNeededCells(map, ray2);
      Assert::AreEqual( cell_list.size(), size_t(5));
      Assert::AreEqual( cell_list[1].first, size_t(3));
      Assert::AreEqual( cell_list[1].second, size_t(3));
      Assert::AreEqual( cell_list[4].first, size_t(3));
      Assert::AreEqual( cell_list[4].second, size_t(0));

      TRay2 ray3 ( TVector2(30, 50), TVector2(2, -3) );
      cell_list = PickNeededCells(map, ray3);
      Assert::AreEqual( cell_list.size(), size_t(1));
      Assert::AreEqual( cell_list[0].first, size_t(3));
      Assert::AreEqual( cell_list[0].second, size_t(3));
      
      TRay2 ray4 ( TVector2(35, 35), TVector2(1, 0) );
      cell_list = PickNeededCells(map, ray4);
      Assert::AreEqual( cell_list.size(), size_t(1));
      Assert::AreEqual( cell_list[0].first, size_t(3));
      Assert::AreEqual( cell_list[0].second, size_t(3));
      }

    TEST_METHOD(ShouldPickCellsWnenXdirNegative)
		  {
			HeightMap map (5, 5);
      TRay2 ray ( TVector2(25, 25), TVector2(-4, 1) );
      auto cell_list = PickNeededCells(map, ray);
      Assert::AreEqual( cell_list.size(), size_t(4));
      Assert::AreEqual( cell_list[1].first, size_t(1));
      Assert::AreEqual( cell_list[1].second, size_t(2));
      Assert::AreEqual( cell_list[3].first, size_t(0));
      Assert::AreEqual( cell_list[3].second, size_t(3));
      
      TRay2 ray1 ( TVector2(20, 30), TVector2(-1, -1) );
      cell_list = PickNeededCells(map, ray1);
      Assert::AreEqual( cell_list.size(), size_t(5));
      Assert::AreEqual( cell_list[0].first, size_t(2));
      Assert::AreEqual( cell_list[0].second, size_t(3));
      Assert::AreEqual( cell_list[4].first, size_t(0));
      Assert::AreEqual( cell_list[4].second, size_t(1));

      TRay2 ray2 ( TVector2(60, 30), TVector2(-1, 0) );
      cell_list = PickNeededCells(map, ray2);
      Assert::AreEqual( cell_list.size(), size_t(4));
      Assert::AreEqual( cell_list[2].first, size_t(1));
      Assert::AreEqual( cell_list[2].second, size_t(3));
      Assert::AreEqual( cell_list[3].first, size_t(0));
      Assert::AreEqual( cell_list[3].second, size_t(3));
      }

    TEST_METHOD(ShouldPickCellsWnenXdirNull)
		  {
			HeightMap map (5, 5);
      TRay2 ray ( TVector2(25, 25), TVector2(0, 0) );
      auto cell_list = PickNeededCells(map, ray);
      Assert::AreEqual( cell_list.size(), size_t(1));
      Assert::AreEqual( cell_list[0].first, size_t(2));
      Assert::AreEqual( cell_list[0].second, size_t(2));
      
      TRay2 ray1 ( TVector2(40, 40), TVector2(0, 0) );
      cell_list = PickNeededCells(map, ray1);
      Assert::AreEqual( cell_list.size(), size_t(1));
      Assert::AreEqual( cell_list[0].first, size_t(3));
      Assert::AreEqual( cell_list[0].second, size_t(3));
      
      TRay2 ray2 ( TVector2(15, 20), TVector2(0, 1) );
      cell_list = PickNeededCells(map, ray2);
      Assert::AreEqual( cell_list.size(), size_t(2));
      Assert::AreEqual( cell_list[1].first, size_t(1));
      Assert::AreEqual( cell_list[1].second, size_t(3));
      
      TRay2 ray3 ( TVector2(40, 40), TVector2(0, -1) );
      cell_list = PickNeededCells(map, ray3);
      Assert::AreEqual( cell_list.size(), size_t(4));
      Assert::AreEqual( cell_list[0].first, size_t(3));
      Assert::AreEqual( cell_list[0].second, size_t(3));
      Assert::AreEqual( cell_list[3].first, size_t(3));
      Assert::AreEqual( cell_list[3].second, size_t(0));

      TRay2 ray4 ( TVector2(25, 40), TVector2(0, 1) );
      cell_list = PickNeededCells(map, ray4);
      Assert::AreEqual( cell_list.size(), size_t(0));
      }

    TEST_METHOD(ShouldNotPickCells)
		  {
			HeightMap map (5, 5);
      TRay2 ray ( TVector2(-10, -10), TVector2(1, -1) );
      auto cell_list = PickNeededCells(map, ray);
      Assert::AreEqual( cell_list.size(), size_t(0));
      
      TRay2 ray1 ( TVector2(40, 0), TVector2(1, 5) );
      cell_list = PickNeededCells(map, ray1);
      Assert::AreEqual( cell_list.size(), size_t(0));
      
      TRay2 ray2 ( TVector2(0, 40), TVector2(1, 0) );
      cell_list = PickNeededCells(map, ray2);
      Assert::AreEqual( cell_list.size(), size_t(0));

      TRay2 ray3 ( TVector2(30, -10), TVector2(1, 1) );
      cell_list = PickNeededCells(map, ray3);
      Assert::AreEqual( cell_list.size(), size_t(0));

      TRay2 ray4 ( TVector2(30, 50), TVector2(1, -1) );
      cell_list = PickNeededCells(map, ray4);
      Assert::AreEqual( cell_list.size(), size_t(0));
      }
	};
}